X-Git-Url: https://git.r.bdr.sh/rbdr/map/blobdiff_plain/f93215a7b37e065a0a52a852bb2c35d2a3d77b0b..144915635bdfc90445321189914929a911fe77d4:/Map/Presentation/Base%20Components/MapTextEditor.swift?ds=sidebyside diff --git a/Map/Presentation/Base Components/MapTextEditor.swift b/Map/Presentation/Base Components/MapTextEditor.swift index 31da790..a7dbe52 100644 --- a/Map/Presentation/Base Components/MapTextEditor.swift +++ b/Map/Presentation/Base Components/MapTextEditor.swift @@ -20,6 +20,19 @@ import SwiftUI class MapTextEditorController: NSViewController { @Binding var document: MapDocument + var highlightRanges: [Range] { + didSet { + updateHighlights() + } + } + + var selectedRange: Int { + didSet { + updateHighlights() + focusOnResult() + } + } + let onChange: () -> Void private let vertexRegex = MapParsingPatterns.vertex @@ -32,9 +45,14 @@ class MapTextEditorController: NSViewController { private let changeDebouncer: Debouncer = Debouncer(seconds: 1) - init(document: Binding, onChange: @escaping () -> Void) { + init( + document: Binding, highlightRanges: [Range], selectedRange: Int, + onChange: @escaping () -> Void + ) { self._document = document self.onChange = onChange + self.highlightRanges = highlightRanges + self.selectedRange = selectedRange super.init(nibName: nil, bundle: nil) } @@ -60,6 +78,50 @@ class MapTextEditorController: NSViewController { override func viewDidAppear() { self.view.window?.makeFirstResponder(self.view) + updateHighlights() + } + + private var textView: NSTextView? { + return (view as? NSScrollView)?.documentView as? NSTextView + } + + private func updateHighlights() { + if let textView { + if let textStorage = textView.textStorage { + textStorage.removeAttribute( + .backgroundColor, range: NSRange(location: 0, length: textStorage.length)) + + for range in highlightRanges { + let nsRange = NSRange(range, in: textStorage.string) + + textStorage.addAttribute(.backgroundColor, value: NSColor.syntax.match, range: nsRange) + } + + textView.needsDisplay = true + + } + } + } + + private func focusOnResult() { + if let textView { + if let textStorage = textView.textStorage { + if selectedRange < highlightRanges.count { + let range = highlightRanges[selectedRange] + let nsRange = NSRange(range, in: textStorage.string) + textView.scrollRangeToVisible(nsRange) + textView.selectedRange = nsRange + } + } + } + } + + private func setSelectionColor() { + guard let textView = self.textView else { return } + + var selectedTextAttributes = textView.selectedTextAttributes + selectedTextAttributes[.backgroundColor] = NSColor.yellow.withAlphaComponent(0.3) + textView.selectedTextAttributes = selectedTextAttributes } } @@ -182,16 +244,23 @@ extension MapTextEditorController: NSTextStorageDelegate { struct MapTextEditor: NSViewControllerRepresentable { @Binding var document: MapDocument + var highlightRanges: [Range] + var selectedRange: Int var onChange: () -> Void = {} func makeNSViewController( context: NSViewControllerRepresentableContext ) -> MapTextEditorController { - return MapTextEditorController(document: $document, onChange: onChange) + return MapTextEditorController( + document: $document, highlightRanges: highlightRanges, selectedRange: selectedRange, + onChange: onChange) } func updateNSViewController( _ nsViewController: MapTextEditorController, context: NSViewControllerRepresentableContext - ) {} + ) { + nsViewController.highlightRanges = highlightRanges + nsViewController.selectedRange = selectedRange + } }